package com.probox.common.entity.service.wechat.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.probox.common.core.constant.CachePrefix;
import com.probox.common.core.enums.DataStatus;
import com.probox.common.core.enums.WechatAuthorizationStatusEnum;
import com.probox.common.core.enums.WechatExchangeBindStatusEnum;
import com.probox.common.core.exception.WechatException;
import com.probox.common.core.utils.SecurityUtils;
import com.probox.common.core.utils.StringUtils;
import com.probox.common.redis.service.RedisService;
import com.probox.common.entity.domain.wechat.WechatAuthorizationInfo;
import com.probox.common.entity.mapper.wechat.WechatAuthorizationInfoMapper;
import com.probox.common.entity.service.wechat.IWechatAuthorizationInfoService;
import com.probox.common.entity.service.wechat.WechatMiniService;
import com.probox.common.entity.service.wechat.WechatPlatformService;
import com.probox.common.entity.domain.wechat.vo.ApiQueryAuthVo;
import com.probox.common.entity.domain.wechat.vo.AuthorizationInfoVo;
import com.probox.common.entity.domain.wechat.vo.ComponentAccessTokenVo;
import com.probox.common.entity.domain.wechat.vo.PreAuthCodeVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class WechatPlatformServiceImpl implements WechatPlatformService {

    @Autowired
    private WechatAuthorizationInfoMapper authorizationInfoMapper;

    @Autowired
    private IWechatAuthorizationInfoService wechatAuthorizationInfoService;


    @Autowired
    private WechatMiniService wechatMiniService;

    //第三方服票据
    private static String ticket = "";
    //第三方服务访问token
    private static String component_access_token = "";

    @Autowired
    RedisService redisService;

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 设置第三方平台的ticket-----公用
     */
    private static final  String ticket_cache_key = CachePrefix.PRE_GLOABLE+"ticket";
    public void setTicket(String t){
        ticket = t;
        logger.info("收到的 ticket = "+ticket);
        redisService.setCacheObject(ticket_cache_key,ticket,10L, TimeUnit.MINUTES);
    }
    public String getTicket(){
        //if (StringUtils.isNotEmpty(ticket)) return ticket;
        Object value = redisService.getCacheObject(ticket_cache_key);
        if (value != null) ticket = (String)value;
        return ticket;
    }


    /**
     * 获得第三方平台访问token-----公用
     */
    private static final  String component_access_token_cache_key = CachePrefix.PRE_GLOABLE+"component_access_token";
    public  String getApiComponentToken(){
        //if (StringUtils.isNotEmpty(component_access_token)) return component_access_token;
        Object value = redisService.getCacheObject(component_access_token_cache_key);
        if (value != null){
            ComponentAccessTokenVo vo = (ComponentAccessTokenVo)value;
            component_access_token = vo.getComponent_access_token();
            return component_access_token;
        }
        getApi_component_token();
        return component_access_token;
    }
    //获取第三方平台访问access_token
    private final static String api_component_token_url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
    public void getApi_component_token(){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("component_appid",appId);
        param.put("component_appsecret",appSecret);
        param.put("component_verify_ticket",getTicket());
        String rst = HttpUtil.post(api_component_token_url, JSON.toJSONString(param));
        logger.info("获取第三方平台access_token 返回值 getApi_component_token rst=>"+rst);
        ComponentAccessTokenVo vo = JSON.parseObject(rst, ComponentAccessTokenVo.class);
        if (vo != null){
            redisService.setCacheObject(component_access_token_cache_key,vo,new Long(vo.getExpires_in()),TimeUnit.SECONDS);
            component_access_token = vo.getComponent_access_token();
            logger.info(" component_access_token = "+component_access_token);
        }
    }


    /**
     * 获得第三方平台的预授权码-----公用
     */
    //获取预授权码
    private final static String api_create_preauthcode_url = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=";
    private static final  String api_create_preauthcode_cache_key = CachePrefix.PRE_GLOABLE+"api_create_preauthcode";
    public String getApiCreatePreauthcode(){
        PreAuthCodeVo vo = null;
//        Object value = redisService.getCacheObject(api_create_preauthcode_cache_key);
//        if (value != null) {
//            vo = (PreAuthCodeVo)value;
//            return vo.getPre_auth_code();
//        }
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("component_appid",appId);
        String rst = HttpUtil.post(api_create_preauthcode_url+getApiComponentToken(),JSON.toJSONString(param));
        logger.info("获取预授权码 返回值 getApiCreatePreauthcode rst=>"+rst);
        vo = JSON.parseObject(rst, PreAuthCodeVo.class);
        if (vo != null){
            redisService.setCacheObject(api_create_preauthcode_cache_key,vo,vo.getExpires_in(),TimeUnit.SECONDS);
            logger.info(" getApiCreatePreauthcode = "+vo.getPre_auth_code());
            return vo.getPre_auth_code();
        }
        return "";
    }



    /**
     * 获得第三方平台访问授权码-----公用
     * 获取authorizer_access_token
     * @param authorization_code
     * @param expires_in 过期时间
     * @param platformid 平台id
     */
    private final static String api_query_auth_url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=";
    private static String api_query_auth_cache_key = CachePrefix.PRE_GLOABLE+"api_query_auth_";
    private static String wechat_bind_authorizerindo = CachePrefix.WECHAT_BIND_AUTHORIZERINDO;
    public String getApi_query_auth(String authorization_code,String expires_in,String platformid,String authorizationType,String authorizationStatus,String allworkAppid,String bindRefreshToken){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("component_appid",appId);
        param.put("authorization_code",authorization_code);
        String rst = HttpUtil.post(api_query_auth_url+this.getApiComponentToken(),JSON.toJSONString(param));
        logger.info("获取 第三方平台授权访问 token rst=>"+rst);
        JSONObject obj = JSONObject.parseObject(rst);
        String errcode =  obj.getString("errcode");
        if("50002".equals(errcode)){
            throw new WechatException("用户受限,可能是用户帐号被冻结或注销");
        }
        ApiQueryAuthVo vo = JSON.parseObject(rst, ApiQueryAuthVo.class);
        try {
            if (vo != null){
                AuthorizationInfoVo ai = vo.getAuthorization_info();
                if(WechatAuthorizationStatusEnum.reuseSubjectRegister.getKey().equals(authorizationStatus)){
                    //保存绑定公众号信息到redis
                    redisService.setCacheObject(wechat_bind_authorizerindo+ai.getAuthorizer_appid(),ai,Long.parseLong(expires_in),TimeUnit.SECONDS);
                    return rst;
                }
                logger.info("=============================开始存入数据库,当前平台id:"+platformid+"类型为:"+authorizationType+"================================");
                //存入数据库
                QueryWrapper<WechatAuthorizationInfo> AuthorizationQueryWrapper = new QueryWrapper<>();
                AuthorizationQueryWrapper.eq("PLATFORM_ID",platformid);
                AuthorizationQueryWrapper.eq("AUTHORIZER_TYPE",authorizationType);
                WechatAuthorizationInfo wechatAuthorizationInfo = authorizationInfoMapper.selectOne(AuthorizationQueryWrapper);
                WechatAuthorizationInfo authorizationInfo = authorizationInfoMapper.selectById(ai.getAuthorizer_appid());
                if (wechatAuthorizationInfo !=null ){
                    //判断是否当前店铺
                    if (authorizationInfo == null){
                        logger.info("==============="+wechatAuthorizationInfo.getAuthorizerAppid()+"开始修改,修改appid:"+ai.getAuthorizer_appid()+"============");
                        UpdateWrapper<WechatAuthorizationInfo> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("AUTHORIZER_APPID",wechatAuthorizationInfo.getAuthorizerAppid());
                        updateWrapper.set("AUTHORIZER_APPID",ai.getAuthorizer_appid());
                        updateWrapper.set("PLATFORM_ID",platformid);
                        updateWrapper.set("AUTHORIZER_TYPE",authorizationType);
                        updateWrapper.set("AUTHORIZER_ACCESS_TOKEN",ai.getAuthorizer_access_token());
                        updateWrapper.set("EXPIRES_IN",ai.getExpires_in());
                        updateWrapper.set("AUTHORIZER_REFRESH_TOKEN",ai.getAuthorizer_refresh_token());
                        updateWrapper.set("UPDATE_TIME",DateUtil.date());
                        updateWrapper.set("DATA_STATUS",DataStatus.valid.getKey());
//                        wechatAuthorizationInfo.setAuthorizerAppid(ai.getAuthorizer_appid());
//                        wechatAuthorizationInfo.setPlatformId(platformid);
//                        wechatAuthorizationInfo.setAuthorizerType(authorizationType);
//                        wechatAuthorizationInfo.setAuthorizerAccessToken(ai.getAuthorizer_access_token());
//                        wechatAuthorizationInfo.setExpiresIn(ai.getExpires_in());
//                        wechatAuthorizationInfo.setAuthorizerRefreshToken(ai.getAuthorizer_refresh_token());
//                        wechatAuthorizationInfo.setUpdateTime(DateUtil.date());
//                        wechatAuthorizationInfo.setDataStatus(DataStatus.valid.getKey());
                        wechatAuthorizationInfoService.update(updateWrapper);
                        logger.info("成功修改APPID为:"+wechatAuthorizationInfo.getAuthorizerAppid()+"的信息");
                        //根据平台id存入数据库
                        if (platformid!=null){
                            redisService.setCacheObject(CachePrefix.PLATFORM_AUTHORIZER_APPID+platformid+"_"+authorizationType,ai.getAuthorizer_appid(),Long.parseLong(expires_in),TimeUnit.SECONDS);
                            logger.info("成功加入缓存,APPID为:"+ai.getAuthorizer_appid());
                        }
                    }else {
                        logger.info("========当前平台id:"+platformid+"=====查询授权方id="+authorizationInfo.getPlatformId()+"===========");
                        if (platformid.equals(authorizationInfo.getPlatformId())){
                            logger.info("==============="+wechatAuthorizationInfo.getAuthorizerAppid()+"开始修改============");
//                        wechatAuthorizationInfo.setAuthorizerAppid(ai.getAuthorizer_appid());
                            wechatAuthorizationInfo.setPlatformId(platformid);
                            wechatAuthorizationInfo.setAuthorizerType(authorizationType);
                            wechatAuthorizationInfo.setAuthorizerAccessToken(ai.getAuthorizer_access_token());
                            wechatAuthorizationInfo.setExpiresIn(ai.getExpires_in());
                            wechatAuthorizationInfo.setAuthorizerRefreshToken(ai.getAuthorizer_refresh_token());
                            wechatAuthorizationInfo.setUpdateTime(DateUtil.date());
                            wechatAuthorizationInfo.setDataStatus(DataStatus.valid.getKey());
                            authorizationInfoMapper.updateById(wechatAuthorizationInfo);
                            logger.info("成功修改APPID为:"+ai.getAuthorizer_appid()+"的信息");
                            //根据平台id存入数据库
                            if (platformid!=null){
                                redisService.setCacheObject(CachePrefix.PLATFORM_AUTHORIZER_APPID+platformid+"_"+authorizationType,ai.getAuthorizer_appid(),Long.parseLong(expires_in),TimeUnit.SECONDS);
                                logger.info("成功加入缓存,APPID为:"+ai.getAuthorizer_appid());
                            }
                        }else {
                            logger.info("==============="+ai.getAuthorizer_appid()+"已经绑定平台id:"+authorizationInfo.getPlatformId()+"============");
                            throw new WechatException("当前Appid:"+ai.getAuthorizer_appid()+"已绑定店铺");
                        }
                    }
                }else {
                    if (authorizationInfo==null){
                        //判断当前授权方appid是否绑定
                        logger.info(ai.getAuthorizer_appid()+"开始新增");
                        WechatAuthorizationInfo wechatauthorizationInfo = new WechatAuthorizationInfo();
                        wechatauthorizationInfo.setAuthorizerType(authorizationType);
                        wechatauthorizationInfo.setPlatformId(platformid);
                        wechatauthorizationInfo.setAuthorizerAppid(ai.getAuthorizer_appid());
                        wechatauthorizationInfo.setAuthorizerAccessToken(ai.getAuthorizer_access_token());
                        wechatauthorizationInfo.setExpiresIn(ai.getExpires_in());
                        wechatauthorizationInfo.setAuthorizerRefreshToken(ai.getAuthorizer_refresh_token());
                        wechatauthorizationInfo.setIsExchangeBind(WechatExchangeBindStatusEnum.notEchangeBind.getKey());
                        if(!StringUtils.isEmpty(allworkAppid)){
                            wechatauthorizationInfo.setBindAllorkappid(allworkAppid);
                        }
                        if(!StringUtils.isEmpty(bindRefreshToken)){
                            wechatauthorizationInfo.setBindRefreshToken(bindRefreshToken);
                        }
                        wechatauthorizationInfo.setCreateTime(DateUtil.date());
                        wechatauthorizationInfo.setDataStatus(DataStatus.valid.getKey());
                        authorizationInfoMapper.insert(wechatauthorizationInfo);
                        logger.info("成功存入数据库=>"+ai.getAuthorizer_appid());
                        //根据平台id存入数据库
                        if (platformid!=null){
                            redisService.setCacheObject(CachePrefix.PLATFORM_AUTHORIZER_APPID+platformid+"_"+authorizationType,ai.getAuthorizer_appid(),Long.parseLong(expires_in),TimeUnit.SECONDS);
                            logger.info("成功加入缓存,APPID为:"+ai.getAuthorizer_appid());
                        }
                    }else {
                        logger.info("==============="+ai.getAuthorizer_appid()+"已经绑定平台id:"+authorizationInfo.getPlatformId()+"============");
                        throw new WechatException("当前Appid"+ai.getAuthorizer_appid()+"已绑定店铺");
                    }
                }
                String key= api_query_auth_cache_key+ai.getAuthorizer_appid();
                redisService.setCacheObject(key,ai,ai.getExpires_in(),TimeUnit.SECONDS);
                return "success";
            }
        }catch (Exception e){
            return ""+e.getMessage();
        }

        return "";
    }

    /**
     * 根据授权方的appId获取授权的访问的token
     * @param authorizerAppid
     * @return
     */
    public String getAuthorizationInfoAccessToken(String authorizerAppid){
        String key= api_query_auth_cache_key+authorizerAppid;
        Object vaule = redisService.getCacheObject(key);
        if (vaule == null){
            this.getApiComponentToken();
            AuthorizationInfoVo api_authorizer_token = getApi_authorizer_token(component_access_token, authorizerAppid, "");
            return api_authorizer_token.getAuthorizer_access_token();
        }else{
            AuthorizationInfoVo rst = (AuthorizationInfoVo)vaule;
            return rst.getAuthorizer_access_token();
        }
    }

    /**
     * 获取/刷新某个授权方接口调用令牌
     */
    private final static String api_authorizer_token_url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=";
    public AuthorizationInfoVo getApi_authorizer_token(String component_access_token,String authorizer_appid,String authorizer_refresh_token){
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("component_appid",appId);
        param.put("authorizer_appid",authorizer_appid);
        param.put("authorizer_refresh_token",authorizer_refresh_token);
        String rst = HttpUtil.post(api_authorizer_token_url+component_access_token,JSON.toJSONString(param));
        JSONObject obj = JSONObject.parseObject(rst);
        if ("61003".equals(obj.getString("errcode")) || "61023".equals(obj.getString("errcode"))){
            QueryWrapper<WechatAuthorizationInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("AUTHORIZER_APPID",authorizer_appid);
            WechatAuthorizationInfo wechatAuthorizationInfo = authorizationInfoMapper.selectOne(queryWrapper);
            if(wechatAuthorizationInfo != null){
                wechatAuthorizationInfo.setDataStatus(DataStatus.delete.getKey());
                authorizationInfoMapper.updateById(wechatAuthorizationInfo);
                throw new WechatException("请授权后重试");
            }
        }
        logger.info("获取/刷新接口调用令牌 rst=>"+rst);
        AuthorizationInfoVo ai = JSON.parseObject(rst, AuthorizationInfoVo.class);
        String key= api_query_auth_cache_key+authorizer_appid;
        redisService.setCacheObject(key,ai,ai.getExpires_in(),TimeUnit.SECONDS);
        String bindKey= wechat_bind_authorizerindo+authorizer_appid;
        redisService.setCacheObject(bindKey,ai,ai.getExpires_in(),TimeUnit.SECONDS);
        return ai;
    }

    /**
     * 向用户发送消息
     */
    private final static String custom_send_url ="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=";
    public void sendMessage(String openId,String query_auth_code){
        Map<String,Object> param = new HashMap<String,Object>();
        Map<String,Object> content = new HashMap<String,Object>();
        param.put("touser",openId);
        param.put("msgtype","text");
        param.put("text",content);
        content.put("content",query_auth_code+"_from_api");

        String rst = HttpUtil.post(custom_send_url+getApi_query_auth(query_auth_code,null,null,null,null,null,null),JSON.toJSONString(param));
        logger.info("给第三方平台用户发送消息 rst=>"+rst);
    }
}
